package org.chen.wordwave.act;

import android.annotation.SuppressLint;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.Nullable;

import com.hjq.toast.Toaster;

import org.chen.wordwave.R;
import org.chen.wordwave.base.BaseActivity;
import org.chen.wordwave.bean.WordListData;
import org.chen.wordwave.init.WordInit;
import org.chen.wordwave.tools.OtherTools;
import org.chen.wordwave.tools.db.DBHelper;
import org.chen.wordwave.tools.http.ApiAddress;
import org.chen.wordwave.tools.http.HttpUtil;
import org.chen.wordwave.tools.http.WordSenDataSet;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class Review extends BaseActivity implements View.OnClickListener {
    private static final String TAG = "ReviewActivity";
    private final List<WordListData> wordDataList = new ArrayList<>();
    private final List<WordListData> hitDataList = new ArrayList<>();
    private int wordLimit = 0;
    private int wordProgress = 1;
    private int wordPosition = 0;
    private int wordId = 1;
    private boolean isFromHitDataList = false;
    private Button favorites;
    private Button sound;
    private String soundUrl;
    private TextView show_name;
    private TextView show_symbol;
    private TextView show_desc;
    private TextView task_view;
    private TextView show_exa_sentence;
    private MediaPlayer mediaPlayer;
    private Button knowing;
    private Button vagueness;
    private Button memorizing;
    private Button forgetting;
    private Context context;
    private boolean show_exa_sentenceIsClickable = true; //解决点击与滑动冲突
    private final ExecutorService executorService = Executors.newFixedThreadPool(4);
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public Integer getLayoutResId() {
        return R.layout.review_fragment;
    }

    @Override
    public void init() {
        this.context = this;

        initView();
        initData(false);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mediaPlayer != null) {
            mediaPlayer.stop();
            mediaPlayer.release();
        }
        // 销毁时存储wordProgress和wordLimit
        DBHelper.setTodayProgress(context, wordProgress, 1);
        DBHelper.setWordLimit(context, wordLimit, 1);

        View bottomBar = findViewById(R.id.botton_bar);
        if (bottomBar != null) {
            bottomBar.setVisibility(View.VISIBLE);
        }
    }

    private void initView() {
        show_name = findViewById(R.id.show_name);
        show_symbol = findViewById(R.id.show_symbol);
        show_desc = findViewById(R.id.show_desc);
        task_view = findViewById(R.id.task_view);
        show_exa_sentence = findViewById(R.id.example_sentence);
        show_exa_sentence.setMovementMethod(ScrollingMovementMethod.getInstance());
        show_exa_sentence.setOnClickListener(this);
        memorizing = findViewById(R.id.memorizing);
        knowing = findViewById(R.id.knowing);
        vagueness = findViewById(R.id.vagueness);
        forgetting = findViewById(R.id.forgetting);
        sound = findViewById(R.id.sound);
        favorites = findViewById(R.id.favorites);
        favorites.setOnClickListener(this);
        memorizing.setOnClickListener(this);
        knowing.setOnClickListener(this);
        vagueness.setOnClickListener(this);
        sound.setOnClickListener(this);
        forgetting.setOnClickListener(this);
        show_desc.setOnClickListener(this);
        buttonOperation(false);
    }

    private void initData(boolean replaced) {
        if (!replaced)
            initWordDataList();
        else {
            wordDataList.clear();
            hitDataList.clear();
        }
        wordPosition = DBHelper.getWordPosition(context, 1);
        wordProgress = DBHelper.getTodayProgress(context, 1);
        wordLimit = DBHelper.getWordLimit(context, 1);
        if (wordPosition >= wordLimit)
            wordPosition = wordLimit - 1;
        DBHelper dbHelper = new DBHelper(context, "Users.db", null, 1);
        SQLiteDatabase db = dbHelper.getReadableDatabase();
        String sql = "select * from wordlist where class_id='" + DBHelper.getBookClassId(context, 1)
                + "' limit " + wordPosition + "," + wordLimit + " ;";
        Cursor cursor = db.rawQuery(sql, null);

        if (cursor.moveToFirst()) {
            sound.setEnabled(true);
            favorites.setEnabled(true);
            wordLimit = Math.min(wordLimit, cursor.getCount());
            wordId = cursor.getInt(cursor.getColumnIndexOrThrow("word_id"));
            Log.e(TAG, wordId + "");
            show_exa_sentenceIsClickable = true;
            show_exa_sentence.setText(R.string.click_to_display_the_definition);
            show_exa_sentence.setGravity(Gravity.CENTER);
            show_name.setText(cursor.getString(cursor.getColumnIndexOrThrow("name")));
            show_symbol.setText(cursor.getString(cursor.getColumnIndexOrThrow("symbol")));
            if (HttpUtil.networkAvailable(context))
                soundUrl = cursor.getString(cursor.getColumnIndexOrThrow("sound"));
            else {
                Toast.makeText(context, R.string.pronunciation_initialization_failed, Toast.LENGTH_SHORT).show();
            }
            displayTaskInfo(wordProgress, wordLimit);
            new Thread(() -> {
                do {
                    addWordDataList(cursor);
                } while (cursor.moveToNext());
                cursor.close();
                db.close();
                dbHelper.close();
            }).start();
        } else {
            sound.setEnabled(false);
            favorites.setEnabled(false);
            show_exa_sentence.setGravity(Gravity.CENTER);
            show_exa_sentenceIsClickable = false;
            if (HttpUtil.networkAvailable(context)) {
                show_exa_sentence.setText(R.string.please_go_to_the_dictionary_to_select_books);
            } else {
                show_exa_sentence.setText(R.string.no_cache_no_network);
            }
        }
    }

    @SuppressLint({"NonConstantResourceId", "RtlHardcoded"})
    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == R.id.sound) {
            if (!wordDataList.isEmpty() && HttpUtil.networkAvailable(context)) {
                mediaPlayer = MediaPlayer.create(context, Uri.parse(soundUrl));
                mediaPlayer.start();
            } else {
                Toast.makeText(context, R.string.pronunciation_initialization_failed, Toast.LENGTH_SHORT).show();
            }
        } else if (id == R.id.example_sentence) {
            if (show_exa_sentenceIsClickable) {
                buttonOperation(!wordDataList.isEmpty());
                if (isFromHitDataList && !hitDataList.isEmpty()) {
                    show_desc.setText(hitDataList.get(0).getDescription());
                    if (hitDataList.get(0).getExampleSentence().equals("null")) {
                        fetchExampleSentence(ApiAddress.getIcibaAddress(hitDataList.get(0).getName()));
                    } else {
                        show_exa_sentence.setText(DBHelper.getExampleSentence(context, hitDataList.get(0).getWordId()));
                    }
                } else {
                    show_desc.setText(wordDataList.get(0).getDescription());
                    if (wordDataList.get(0).getExampleSentence().equals("null")) {
                        if (HttpUtil.networkAvailable(context))
                            fetchExampleSentence(ApiAddress.getIcibaAddress(wordDataList.get(0).getName()));
                        else {
                            show_exa_sentence.setText(R.string.word_no_cache_network);
                            show_exa_sentence.setGravity(Gravity.CENTER);
                        }
                    } else {
                        show_exa_sentence.setText(DBHelper.getExampleSentence(context, wordDataList.get(0).getWordId()));
                    }
                }
            }
        } else if (id == R.id.memorizing) {
            if (!wordDataList.isEmpty())
                wordOperation(100, DBHelper.MEMORIZING);
        } else if (id == R.id.knowing) {
            if (!wordDataList.isEmpty())
                wordOperation(80, DBHelper.KNOWING);
        } else if (id == R.id.vagueness) {
            if (!wordDataList.isEmpty())
                wordOperation(60, DBHelper.VAGUENESS);
        } else if (id == R.id.forgetting) {
            if (!wordDataList.isEmpty())
                wordOperation(40, DBHelper.FORGETTING);
        } else if (id == R.id.favorites) {
            if (WordInit.userInfo.getEmail() != null){
                if (!hitDataList.isEmpty() && !wordDataList.isEmpty()) {
                    Toast.makeText(context, R.string.no_word_data, Toast.LENGTH_SHORT).show();
                    return;
                }
                DBHelper.setFavorites(context, DBHelper.FAVORITES, wordId);
                DBHelper dbHelper = new DBHelper(context, "Users.db", null, 1);
                SQLiteDatabase db = dbHelper.getReadableDatabase();
                String sql = "select * from wordlist where word_id=" + wordId + ";";
                String name;
                try (Cursor cursor = db.rawQuery(sql, null)) {
                    cursor.moveToFirst();
                    name = cursor.getString(cursor.getColumnIndexOrThrow("name"));
                }
                db.close();
                Log.e(TAG, "wordId: " + wordId + " name: " + name);
                Toaster.show(R.string.Favorite);
            }else {
                Toaster.show(R.string.need_login);
            }
        }
    }

    private void wordOperation(int possibility, int word_operation) {
        buttonOperation(false);
        if (wordProgress < wordLimit) {
            new Thread(() -> {
                DBHelper.setTimeStamp(context, OtherTools.getCurrentTimeMillis(), wordId);
                DBHelper.setMemory(context, 100, wordId);
                DBHelper.setWordOperation(context, word_operation, wordId);
                if (OtherTools.random_hit(possibility)) {
                    hitDataList.add(wordDataList.get(0));
                }
            }).start();
            prepareNextData();
        } else if (wordProgress == wordLimit) {
            Toast.makeText(context, R.string.TASK_COMPLETED, Toast.LENGTH_SHORT).show();
            wordDataList.clear();
            hitDataList.clear();
        }
    }

    private void prepareNextData() {
        if (!hitDataList.isEmpty())
            isFromHitDataList = OtherTools.random_hit(50);
        if (isFromHitDataList && !hitDataList.isEmpty()) {
            Log.d(TAG, "showNextData: word is From hitDataList");
            wordId = hitDataList.get(0).getWordId();
            show_name.setText(hitDataList.get(0).getName());
            show_symbol.setText(hitDataList.get(0).getSymbol());
            if (HttpUtil.networkAvailable(context))
                soundUrl = hitDataList.get(0).getSound();
            else
                Toast.makeText(context, R.string.due_to_network, Toast.LENGTH_LONG).show();
            show_desc.setText(null);
            show_exa_sentence.setText(R.string.click_to_display_the_definition);
            show_exa_sentence.setGravity(Gravity.CENTER);
        } else {
            if (!wordDataList.isEmpty()) {
                Log.d(TAG, "showNextData: word is From wordDataList");
                wordId = wordDataList.get(0).getWordId();
                show_name.setText(wordDataList.get(0).getName());
                show_symbol.setText(wordDataList.get(0).getSymbol());
                show_desc.setText(null);
                show_exa_sentence.setText(R.string.click_to_display_the_definition);
                show_exa_sentence.setGravity(Gravity.CENTER);
                if (HttpUtil.networkAvailable(context))
                    soundUrl = wordDataList.get(0).getSound();
                else {
                    Toast.makeText(context, R.string.pronunciation_initialization_failed, Toast.LENGTH_SHORT).show();
                }
                displayTaskInfo(++wordProgress, wordLimit);
            } else if (!hitDataList.isEmpty()) {
                Log.d(TAG, "showNextData: word is From hitDataList");
                wordId = hitDataList.get(0).getWordId();
                show_name.setText(hitDataList.get(0).getName());
                show_symbol.setText(hitDataList.get(0).getSymbol());
                if (HttpUtil.networkAvailable(context))
                    soundUrl = hitDataList.get(0).getSound();
                else {
                    Toast.makeText(context, R.string.pronunciation_initialization_failed, Toast.LENGTH_SHORT).show();
                }
                show_desc.setText(null);
                show_exa_sentence.setText(R.string.click_to_display_the_definition);
                show_exa_sentence.setGravity(Gravity.CENTER);
            } else {
                Toast.makeText(context, R.string.TASK_COMPLETED, Toast.LENGTH_SHORT).show();
            }
        }
    }

    private void addWordDataList(Cursor cursor) {
        WordListData wordListData = new WordListData();
        wordListData.setWordId(cursor.getInt(cursor.getColumnIndexOrThrow("word_id")));
        wordListData.setDescription(cursor.getString(cursor.getColumnIndexOrThrow("desc_")));
        wordListData.setName(cursor.getString(cursor.getColumnIndexOrThrow("name")));
        wordListData.setSymbol(cursor.getString(cursor.getColumnIndexOrThrow("symbol")));
        wordListData.setMsg(cursor.getString(cursor.getColumnIndexOrThrow("msg")));
        wordListData.setClassId(cursor.getString(cursor.getColumnIndexOrThrow("class_id")));
        wordListData.setSound(cursor.getString(cursor.getColumnIndexOrThrow("sound")));
        wordListData.setMemory(cursor.getInt(cursor.getColumnIndexOrThrow("memory")));
        wordListData.setExampleSentence(cursor.getString(cursor.getColumnIndexOrThrow("example_sentence")));
        wordListData.setFavorites(cursor.getInt(cursor.getColumnIndexOrThrow("favorites")));
        wordDataList.add(wordListData);
    }

    private void initWordDataList() {
        new Thread(() -> {
            DBHelper dbHelper = new DBHelper(context, "Users.db", null, 1);
            SQLiteDatabase db = dbHelper.getReadableDatabase();
            String sql = "select * from wordlist where class_id='" + DBHelper.getBookClassId(context, 1)
                    + "' and memory<40 and word_operation!=" + DBHelper.MEMORIZING + " limit " + wordPosition + " ;";
            Cursor cursor = db.rawQuery(sql, null);
            if (cursor.moveToFirst() && cursor.getCount() != 0) {
                do {
                    int memory = DBHelper.getMemory(context, cursor.getInt(cursor.getColumnIndexOrThrow("word_id")));
                    if (OtherTools.random_hit(memory)) {
                        addWordDataList(cursor);
                    }
                } while (cursor.moveToNext());

            }
            cursor.close();
            db.close();
            dbHelper.close();
            wordId = wordDataList.isEmpty() ? 0 : wordDataList.get(0).getWordId();
        }).start();
    }

    private void displayTaskInfo(int progress, int wordLimit) {
        if (progress > wordLimit)
            progress = wordLimit;
        String info = progress + " / " + wordLimit;
        task_view.setText(info);
    }

    private void buttonOperation(boolean visibility) {
        if (visibility) {
            show_exa_sentenceIsClickable = false; //解决冲突
            show_desc.setClickable(false);
            memorizing.setVisibility(View.VISIBLE);
            knowing.setVisibility(View.VISIBLE);
            vagueness.setVisibility(View.VISIBLE);
            forgetting.setVisibility(View.VISIBLE);
        } else {
            show_exa_sentenceIsClickable = true;
            show_desc.setClickable(true);
            memorizing.setVisibility(View.INVISIBLE);
            knowing.setVisibility(View.INVISIBLE);
            vagueness.setVisibility(View.INVISIBLE);
            forgetting.setVisibility(View.INVISIBLE);
            if (!hitDataList.isEmpty() && isFromHitDataList) {
                Log.d(TAG, "hitDataList " + hitDataList.get(0).getName() + " is removed");
                hitDataList.remove(0);
            } else if (!wordDataList.isEmpty()) {
                Log.d(TAG, "wordDataList " + wordDataList.get(0).getName() + " is removed");
                wordDataList.remove(0);
            }
        }
    }

    private void fetchExampleSentence(String url) {
        executorService.execute(() -> {
            OkHttpClient client = new OkHttpClient();
            Request request = new Request.Builder().url(url).build();
            try {
                Response response = client.newCall(request).execute();
                String responseBody = Objects.requireNonNull(response.body()).string();
                String text = WordSenDataSet.parseXmlWithPull(responseBody, true);
                DBHelper.setExampleSentence(context, text, wordId);
                new Handler(Looper.getMainLooper()).post(() -> {
                    show_exa_sentence.setText(text);
                    show_exa_sentence.setGravity(Gravity.START);
                });
            } catch (IOException e) {
                Log.d(TAG, "Error fetching example sentence: ", e);
            }
        });
    }
}

